home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 April: Mac OS SDK / Dev.CD Apr 97 SDK1.toast / Development Kits (Disc 1) / Apple Shared Library Manager / ASLM Examples / Inspector / Sources / Inspector.cp < prev    next >
Encoding:
Text File  |  1996-11-19  |  25.4 KB  |  956 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Inspector.cp
  3.  
  4.     Contains:    A test application class for testing the ASLM.
  5.  
  6.     Copyright:    © 1991-1995 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10. #ifndef __MENUS__
  11. #include <Menus.h>
  12. #endif
  13. #ifndef __EVENTS__
  14. #include <Events.h>
  15. #endif
  16. #ifndef __WINDOWS__
  17. #include <Windows.h>
  18. #endif
  19. #ifndef __DIALOGS__
  20. #include <Dialogs.h>
  21. #endif
  22. #ifndef __QUICKDRAW__
  23. #include <Quickdraw.h>
  24. #endif
  25. #ifndef __MEMORY__
  26. #include <Memory.h>
  27. #endif
  28. #ifndef __RESOURCES__
  29. #include <Resources.h>
  30. #endif
  31. #ifndef __FILES__
  32. #include <Files.h>
  33. #endif
  34. #ifndef __STANDARDFILE__
  35. #include <StandardFile.h>
  36. #endif
  37. #ifndef __FOLDERS__
  38. #include <Folders.h>
  39. #endif
  40. #ifndef __LOWMEM__
  41. #include <LowMem.h>
  42. #endif
  43. #ifndef __ERRORS__
  44. #include <Errors.h>
  45. #endif
  46.  
  47.  
  48. #ifndef __TESTTOOL__
  49. #include <TestTool.h>
  50. #endif
  51. #ifndef __INSPECTOR__
  52. #include "Inspector.h"
  53. #endif
  54. #ifndef __WINDOWSTACKER__
  55. #include "WindowStacker.h"
  56. #endif
  57. #ifndef __INSPECTORCOMMON__
  58. #include "InspectorCommon.h"
  59. #endif
  60. #ifndef __REGISTEREDOBJECTSWINDOW__
  61. #include "RegisteredObjectsWindow.h"
  62. #endif
  63. #ifndef __LIBRARYMANAGERUTILITIES__
  64. #include <LibraryManagerUtilities.h>
  65. #endif
  66. #ifndef __STRING__
  67. #include <string.h>
  68. #endif
  69. #ifndef __STRINGS__
  70. #include <Strings.h>
  71. #endif
  72.  
  73. /**********************************************************************
  74. ** PUBLIC Constructor
  75. ***********************************************************************/
  76.  
  77. TInspector::TInspector(QDGlobals* qdPtr, BooleanParm initToolbox)
  78.     : TApplication(qdPtr,initToolbox)
  79. {
  80.     fVerbose    = true;
  81.     fDebug        = false;
  82.     fDoLoad        = true;
  83.     fGrowPool    = true;
  84.     fIterationCount = 1;
  85.     
  86.     OpenPrefsFile();
  87.  
  88.     fLibraryManagerCmd = kNoCmd;
  89.     fUpdateListsScheduler = new TSerialScheduler;
  90.     // we need to set the scheduler's client to ourself because the
  91.     // TOperations are created by ASLM, but we want them to execute
  92.     // in our global world and with us as the current client, not ASLM.
  93.     fUpdateListsScheduler->SetSchedulerClient(::GetCurrentClient());
  94.     fNextWindowLocation.v = kWindowVStart;
  95.     fNextWindowLocation.h = kWindowHStart;
  96.     fHTopWindowLocation = fNextWindowLocation.h + kWindowHResetStagger;
  97.     GetLocalLibraryManager()->TraceLogOn();
  98.  
  99.     ::RegisterInspector(this);
  100.  
  101.     // read menus into menu bar
  102.  
  103.     long savedRefNum;
  104.     GetLocalLibraryFile()->Preflight(savedRefNum);
  105.     Handle menuBar = GetNewMBar(rMenuBar);
  106.     DebugFailNULL(menuBar, resNotFound, "TInspector::InitInspector: could not get menubar.");
  107.  
  108.     // install menus
  109.     SetMenuBar(menuBar);
  110.     DisposeHandle(menuBar);
  111.     // add DA names to Apple menu
  112.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  113.     DrawMenuBar();
  114.     GetLocalLibraryFile()->Postflight(savedRefNum);
  115.  
  116.     // create empty mouse region
  117.     fMouseRgn = NewRgn();
  118.     // make sure we have a valid cursor region
  119.     AdjustCursor();
  120. }
  121.  
  122. TInspector::~TInspector()
  123. {
  124.     Trace("Disposing TInspector\n");
  125.  
  126.     //
  127.     // save all window sizes and locations in the prefs file
  128.     //
  129.     TDocumentLink*    theDocLink = DocList()->FirstDoc();
  130.     while (theDocLink)
  131.     {
  132.         ((TRegisteredObjectsWindow*)theDocLink->GetDoc())->SaveWindowLocation();
  133.         theDocLink = theDocLink->GetNext();
  134.     }
  135.  
  136.     ::RegisterInspector(NULL);
  137.     
  138.     fUpdateListsScheduler->Run();    // make sure all operations get processed first
  139.     delete fUpdateListsScheduler;
  140.  
  141.     DisposeHandle(Handle(fMouseRgn));
  142.     
  143.     ClosePrefsFile();
  144. }
  145.  
  146. /**********************************************************************
  147. ** PUBLIC DoIdle
  148. ***********************************************************************/
  149.  
  150. void TInspector::DoIdle()
  151. {
  152.     /* Make sure all of our TLists are up-to-date */
  153.     fUpdateListsScheduler->Run();
  154. }
  155.  
  156. /**********************************************************************
  157. ** PUBLIC AdjustMenus
  158. ***********************************************************************/
  159.  
  160. // Enable and disable menus based on the current state. The
  161. // user can only select enabled menu items. We set up all the
  162. // menu items before calling MenuSelect or MenuKey, since
  163. // these are the only times that a menu item can be selected.
  164. // Note that MenuSelect is also the only time the user will
  165. // see menu items. This approach to deciding what enable/
  166. // disable state a menu item has the advantage of
  167. // concentrating all the decision-making in one routine, as
  168. // opposed to being spread throughout the application. Other
  169. // application designs may take a different approach that may
  170. // or may not be as valid. 
  171.  
  172. void ExactAppend(MenuHandle aMenu, Str255 aString)
  173. {
  174.     unsigned char fillString[128];
  175.     /* Since AppendMenu will interpret meta-characters, first append a menu item with    */
  176.     /* no meta-characters, but which has the same length as aString, then set the menu    */
  177.     /* item to astring (SetMenuItemText doesn't interpret meta-characters). */
  178.     fillString[0] = aString[0];
  179.     if (aString[0])
  180.         memset(fillString + 1, 'a', aString[0]);
  181.     AppendMenu(aMenu, fillString);
  182.     SetMenuItemText(aMenu, CountMItems(aMenu), aString);
  183. }    
  184.     
  185. void TInspector::AdjustMenus(void)
  186. {
  187.     WindowPtr    frontmost;
  188.     MenuHandle    menu;
  189.     Boolean        undo;
  190.     Boolean        cutCopyClear;
  191.     Boolean        paste;
  192.     short        i;        // menu item index
  193.  
  194.     frontmost = FrontWindow();
  195.  
  196.     long savedRefNum;
  197.     GetLocalLibraryFile()->Preflight(savedRefNum);
  198.  
  199.     //
  200.     // Edit menu
  201.     //
  202.  
  203.     menu = GetMenuHandle(mEdit);
  204.     DebugFailNULL(menu, resNotFound, "TInspector::AdjustMenus: could not get Edit menu.");
  205.  
  206.     undo = false;
  207.     cutCopyClear = false;
  208.     paste = false;
  209.     if (frontmost != NULL) {
  210.         if (fCurDoc == NULL) {
  211.             undo = true;                // all editing is enabled for DA windows 
  212.             cutCopyClear = true;
  213.             paste = true;
  214.         }
  215.     }
  216.  
  217.     if (undo)
  218.         EnableItem(menu, iUndo);
  219.     else
  220.         DisableItem(menu, iUndo);
  221.  
  222.     if (cutCopyClear) {
  223.         EnableItem(menu, iCut);
  224.         EnableItem(menu, iCopy);
  225.         EnableItem(menu, iClear);
  226.     } 
  227.     else {
  228.         DisableItem(menu, iCut);
  229.         DisableItem(menu, iCopy);
  230.         DisableItem(menu, iClear);
  231.     }
  232.     if (paste)
  233.         EnableItem(menu, iPaste);
  234.     else
  235.         DisableItem(menu, iPaste);
  236.  
  237.     //
  238.     // File Menu
  239.     //
  240.  
  241.     menu = GetMenuHandle(mFile);
  242.     DebugFailNULL(menu, resNotFound, "TInspector::AdjustMenus: could not get File menu.");
  243.     if (frontmost != NULL)
  244.         EnableItem(menu,iClose);
  245.     else
  246.         DisableItem(menu,iClose);
  247.  
  248.     //
  249.     // Windows Menu
  250.     //
  251.  
  252.     menu = GetMenuHandle(mWindows);
  253.     DebugFailNULL(menu, resNotFound, "TInspector::AdjustMenus: could not get Windows menu.");
  254.  
  255.     /* remove all documents from the Windows menu */
  256.     for (i=CountMItems(menu); i>=kWindowListStart; i--)
  257.         DeleteMenuItem(menu, i);
  258.  
  259.     /* add all the documents to the Windows menu */
  260.     int numItems = kWindowListStart-1;
  261.     TDocumentLink *theLink = DocList()->FirstDoc();
  262.     while (theLink)
  263.     {
  264.         TDocument *theDoc = theLink->GetDoc();
  265.         Str255 tempString;
  266.         GetWTitle(theDoc->GetDocWindow(),tempString);
  267.         ExactAppend(menu,tempString);
  268.         theLink = theLink->GetNext();
  269.         numItems++;
  270.         CheckItem(menu,numItems,fCurDoc == theDoc);
  271.         fWindowsMenuDocList[numItems-kWindowListStart] = theDoc;
  272.     }
  273.  
  274.     //
  275.     // Tests Menu 
  276.     //
  277.  
  278.     menu = GetMenuHandle(mTests);
  279.     DebugFailNULL(menu, resNotFound, "TInspector::AdjustMenus: could not get Tests menu.");
  280.  
  281.     CheckItem(menu, iVerbose, fVerbose);
  282.     CheckItem(menu, iDebug, fDebug);
  283.     CheckItem(menu, iDoLoad, fDoLoad);
  284.     CheckItem(menu, iGrowPool, fGrowPool);
  285.  
  286.     /* remove all tests from the Tests menu */
  287.     for (i=CountMItems(menu); i>=kTestsListStart; i--)
  288.     {
  289.         delete fTestsMenuTestList[i-kTestsListStart];
  290.         DeleteMenuItem(menu, i);
  291.     }
  292.  
  293.     /* add all the tests to the Tests menu */
  294.     TClassID*    testname;
  295.     size_t        testnamelen;
  296.     size_t        testToolPrefixLen = strlen(kTestToolPrefix);
  297.     OSErr        err;
  298.     TClassInfo*    info = GetClassInfo(ClassID(kTTestToolID), &err);
  299.  
  300.     fNumTests = 0;
  301.     if (info)
  302.     {
  303.         while ((testname = (TClassID*)info->Next()) != NULL)
  304.         {
  305.             testnamelen = strlen(*testname);
  306.             fTestsMenuTestList[fNumTests] = new (testnamelen) TClassID(*testname);
  307.             DebugFailNULL(fTestsMenuTestList[fNumTests], kASLMOutOfMemoryErr, 
  308.                 "TInspector::AdjustMenus: could not allocate TClassID*.");
  309.             Str255 itemname;
  310.             memmove(&itemname[1], (char*)testname + testToolPrefixLen, testnamelen - testToolPrefixLen + 1);
  311.             itemname[0] = testnamelen - testToolPrefixLen + 1;
  312.             ExactAppend(menu,itemname);
  313.             if (++fNumTests >= kMaxTests)
  314.                 break;
  315.         }
  316.         delete info;
  317.     }
  318.  
  319.     GetLocalLibraryFile()->Postflight(savedRefNum);
  320. }
  321.  
  322. /**********************************************************************
  323. ** PUBLIC AdjustCursor
  324. ***********************************************************************/
  325.  
  326. void TInspector::AdjustCursor()
  327. {
  328.     SetCursor(&fqd->arrow);
  329. }
  330.  
  331. /**********************************************************************
  332. ** isKeyDown
  333. ***********************************************************************/
  334.  
  335. #define kOptionKeyCode     58
  336.  
  337. static Boolean isKeyDown(long keyCode)
  338. {
  339.     KeyMap keys;
  340.     Byte *keysBytes;
  341.     
  342.     GetKeys(keys);
  343.     
  344.     keysBytes = (Byte *)keys;
  345.  
  346.     return((keysBytes[keyCode/8] & (1 << keyCode % 8)) != 0);
  347. }
  348.  
  349. /*******************************************************************************
  350. ** ChooseFolderItemHandler
  351. **
  352. ** Custom item handler for selecting directories. We use a modified SFGetFile
  353. ** dialog which has a "Select Current Folder" button and a "Select" button.
  354. ********************************************************************************/
  355.  
  356. SFReply gChooseFolderReply;
  357. short    gSFVRefNum;
  358. long    gSFDirID;
  359.  
  360. static pascal short ChooseFolderItemHandler(short item, DialogPtr theDialog)
  361. {
  362.     // constants for items passed to this dialog handler
  363.     const short selectHilitedFolderButton = 11;     /* item number for the "Select Current Directory" button */
  364.     const short selectCurrentFolderButton = 13;     /* item number for the "Select" button */
  365.     const escapeKey    = 0x1000 + 27;                    /* "item" number for the escape key */
  366.  
  367.     short    itemType;            /* type of the SFGetFile Open button */
  368.     Handle    itemHdl;             /* handle to SFGetFile Open button item */
  369.     Rect    itemRect;            /* rect of the SFGetFile Open button */
  370.     short    newState;            /* the new Hilite state to set the "select" button to */
  371.  
  372.     /* if no directory is selected then dim the "Select" button.  Otherwise */
  373.     /* just turn it on normally. */
  374.  
  375.     /* the fType field of the Reply record will contain the DirID of the hilited    */
  376.     /* folder if one is hilited.  Otherwise it will contain 0.    */
  377.     if (gChooseFolderReply.fType == 0)
  378.         newState = 255;                        /* dim the "select" button */
  379.     else
  380.         newState = 0;                        /* turn on the "select" button */
  381.  
  382.     /* Only set the hilite state and redraw if the state has changed.  This */
  383.     /* prevents the button from flickering. */
  384.     GetDialogItem(theDialog, selectHilitedFolderButton, &itemType, &itemHdl, &itemRect);
  385.     if (newState != (**(ControlHandle)itemHdl).contrlHilite)
  386.     {
  387.         HiliteControl(ControlHandle(itemHdl), newState);
  388.         Draw1Control(ControlHandle(itemHdl));
  389.     };
  390.  
  391.     /* act on the item hit */
  392.     switch (item)
  393.     {
  394.         case escapeKey:                        /* if they hit the escape key then generate a cancel */
  395.             return getCancel;
  396.  
  397.         case selectHilitedFolderButton:        /* the "Select Current Folder" button was pressed */
  398.         case selectCurrentFolderButton:        /* the "Select" button was pressed */
  399.         {
  400.             /* The user has made his choice of folders.  We need to put the volume of the    */
  401.             /* folder into gSavSFVolume and the DirID into gSavSFDirID. */
  402.         
  403.             gSFVRefNum = -LMGetSFSaveDisk(); /* get the current volume */
  404.  
  405.             /* If the "select" button has been pressed then choose the hilited folder.    */
  406.             /* The DirID of the hilited folder is always in the fType filed of the reply    */
  407.             /* record. */
  408.             if (item == selectHilitedFolderButton)
  409.                 gSFDirID = (long)gChooseFolderReply.fType;
  410.  
  411.             /* otherwise we want the currently opened folder whose DirID is stored in    */
  412.             /* the low memory global "CurDirStor". */
  413.             else
  414.                 gSFDirID = LMGetCurDirStore();
  415.  
  416.             /* tell SFPGetFile to "open" the folder, "open" meaning "select" not enter */
  417.             return getOpen;
  418.         }
  419.  
  420.         default:                            /* Normally, we just return the item */
  421.             return item;
  422.     }
  423. }
  424.  
  425. /*******************************************************************************
  426. ** MySFFileFilter
  427. **
  428. ** This filter is used when we are selecting a folder. Since
  429. ** we don't want to display any files we always return TRUE.
  430. ********************************************************************************/
  431.  
  432. static pascal Boolean MySFFileFilter( ParmBlkPtr)
  433. {
  434.     return true;
  435. };
  436.  
  437. /**********************************************************************
  438. ** PUBLIC DoMenuCommand
  439. ***********************************************************************/
  440.  
  441. // This is called when an item is chosen from the menu bar (after calling
  442. // MenuSelect or MenuKey). It does the right thing for each command.
  443.  
  444. // static TDynamic* gExampleObject;
  445.  
  446. void TInspector::DoMenuCommand(short menuID, short menuItem)
  447. {
  448.     short        itemHit;
  449.     Str255        daName;
  450.     short        daRefNum;
  451.     WindowPtr    window;
  452.  
  453.     window = FrontWindow();
  454.     switch (menuID) {
  455.         case mApple:
  456.             switch (menuItem) {
  457.                 case iAbout:        // bring up alert for About 
  458.                     itemHit = Alert(rAboutAlert, NULL);
  459.                     break;
  460.                 default:            // all non-About items in this menu are DAs et al 
  461.                     long savedRefNum;
  462.                     GetLocalLibraryFile()->Preflight(savedRefNum);
  463.                     GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
  464.                     GetLocalLibraryFile()->Postflight(savedRefNum);
  465.                     daRefNum = OpenDeskAcc(daName);
  466.                     break;
  467.             }
  468.             break;
  469.  
  470.         case mFile:
  471.             switch (menuItem) {
  472.                 case iQuit:
  473.                     Terminate();
  474.                     break;
  475.                 case iClose:
  476.                     if (fCurDoc != NULL) {
  477.                         HideWindow(fCurDoc->GetDocWindow());
  478.                     }
  479.                     else
  480.                         CloseDeskAcc(((WindowPeek) fWhichWindow)->windowKind);
  481.                     // make sure our current document/window references are valid
  482.                     fWhichWindow = FrontWindow();
  483.                     if (fWhichWindow != NULL) {
  484.                         fCurDoc = fDocList->FindDoc(fWhichWindow);
  485.                         SetPort(fWhichWindow);
  486.                     }
  487.                     else
  488.                         fCurDoc = NULL;
  489.                     break;
  490.             }
  491.             break;
  492.  
  493.         case mEdit:                    // call SystemEdit for DA editing & MultiFinder 
  494.             if (!SystemEdit(menuItem-1))
  495.                 DebugBreak("Oops.  SystemEdit returned false.");
  496.             break;
  497.         
  498.         case mWindows: {
  499.                 switch (menuItem) {
  500.                     case iStack: {
  501.                             fNextWindowLocation.v = kWindowVStart;
  502.                             fNextWindowLocation.h = kWindowHStart;
  503.                             TRY
  504.                                 TWindowStacker* stacker = new TWindowStacker(kWindowHStagger, kWindowVStagger);
  505.                                 if (stacker)
  506.                                     stacker->StackWindows(fNextWindowLocation.h,fNextWindowLocation.v);
  507.                                 delete stacker;
  508.                             CATCH_ALL
  509.                                 AlertUser(kInspectorErrStrings, kWindowStackerLibraryMissing);
  510.                             ENDTRY
  511.                         }
  512.                         break;
  513.                         
  514.                     case iRefresh:
  515.                         {
  516.                             TRegisteredObjectsWindow* theWindow =
  517.                                 (TRegisteredObjectsWindow*)DocList()->FindDoc(FrontWindow());
  518.                             if (theWindow)
  519.                                 theWindow->UpdateList();
  520.                         }
  521.                         
  522.                         #if 0
  523.                         if (gExampleObject == NULL)
  524.                             gExampleObject = (TDynamic*)GetLocalLibraryManager()->NewObject(ClassID("appl:exam$TExampleClass,1.1"),NULL,::GetSystemPool());
  525.                         else
  526.                         {
  527.                             delete gExampleObject;
  528.                             gExampleObject = NULL;
  529.                         }
  530.                         #endif
  531.                         break;
  532.                         
  533.                     case iRefreshAll:
  534.                         {
  535.                             TDocumentLink*    theDocLink = DocList()->FirstDoc();
  536.                             while (theDocLink)
  537.                             {
  538.                                 ((TRegisteredObjectsWindow*)theDocLink->GetDoc())->UpdateList();
  539.                                 theDocLink = theDocLink->GetNext();
  540.                             }
  541.                         }
  542.                         break;
  543.                         
  544.                     case iHome:
  545.                         {
  546.                             TRegisteredObjectsWindow* theWindow = (TRegisteredObjectsWindow*)DocList()->FindDoc(FrontWindow());
  547.                             if (theWindow)
  548.                                 theWindow->HomeWindow();
  549.                         }
  550.                         break;
  551.                         
  552.                     default:
  553.                         TDocument* theDoc = fWindowsMenuDocList[menuItem-kWindowListStart];
  554.                         if (theDoc)
  555.                         {
  556.                             ShowWindow(theDoc->GetDocWindow());
  557.                             SelectWindow(theDoc->GetDocWindow());
  558.                         }
  559.                         break;
  560.                 }
  561.                 
  562.             }
  563.             break;
  564.         
  565.         case mCommands:
  566.             switch (menuItem) {
  567.                 case iRegisterFolder:
  568.                 {
  569.                     SFTypeList    typelist;
  570.                     Point where = {100,150};
  571.                     long savedRefNum;
  572.                     GetLocalLibraryFile()->Preflight(savedRefNum);
  573.  
  574.                     FileFilterUPP    theFileFilterUPP = NewFileFilterProc(MySFFileFilter);
  575.                     DlgHookUPP        theDialogHookUPP = NewDlgHookProc(ChooseFolderItemHandler);
  576.                     SFPGetFile(where,(ConstStr255Param)"\p",theFileFilterUPP,0,typelist,theDialogHookUPP,
  577.                         &gChooseFolderReply,rFolderDialog,NULL);
  578.                     DisposeRoutineDescriptor(theFileFilterUPP);
  579.                     DisposeRoutineDescriptor(theDialogHookUPP);
  580.  
  581.                     GetLocalLibraryFile()->Postflight(savedRefNum);
  582.                     if (gChooseFolderReply.good)
  583.                     {
  584.                         TMacFileSpec fileSpec(gSFVRefNum, gSFDirID, (unsigned char *)"\p");
  585.                         OSErr result = RegisterLibraryFileFolder(&fileSpec);
  586.                         if (result)
  587.                             DebugBreak("RegisterLibraryFileFolder failed");
  588.                     }
  589.                     break;
  590.                 }
  591.                 case iUnregisterFolder:
  592.                 {
  593.                     SFTypeList    typelist;
  594.                     Point where = {100,150};
  595.                     long savedRefNum;
  596.                     GetLocalLibraryFile()->Preflight(savedRefNum);
  597.  
  598.                     FileFilterUPP    theFileFilterUPP = NewFileFilterProc(MySFFileFilter);
  599.                     DlgHookUPP        theDialogHookUPP = NewDlgHookProc(ChooseFolderItemHandler);
  600.                     SFPGetFile(where,(ConstStr255Param)"\p",theFileFilterUPP,0,typelist,theDialogHookUPP,
  601.                         &gChooseFolderReply,rFolderDialog,NULL);
  602.                     DisposeRoutineDescriptor(theFileFilterUPP);
  603.                     DisposeRoutineDescriptor(theDialogHookUPP);
  604.  
  605.                     GetLocalLibraryFile()->Postflight(savedRefNum);
  606.                     if (gChooseFolderReply.good)
  607.                     {
  608.                         TMacFileSpec fileSpec(gSFVRefNum, gSFDirID, (unsigned char *)"\p");
  609.                         OSErr result = UnregisterLibraryFileFolder(
  610.                             &fileSpec, isKeyDown(kOptionKeyCode));
  611.                         if (result)
  612.                             DebugBreak("UnregisterLibraryFileFolder failed");
  613.                     }
  614.                     break;
  615.                 }
  616.                 case iRegisterFile:
  617.                 {
  618.                     SFTypeList    typelist;
  619.                     Point where = {100,150};
  620.                     SFReply reply;
  621.                     SFGetFile(where,(ConstStr255Param)"\pSelect a library file",NULL,-1,typelist,NULL,&reply);
  622.                     if (reply.good)
  623.                     {
  624.                         TMacFileSpec fileSpec(0,0,reply.fName);
  625.                         long    procID;
  626.                         GetWDInfo(reply.vRefNum,&fileSpec.fVRefNum,&fileSpec.fParID, &procID);
  627.                         TLibraryFile*    libFile;
  628.                         OSErr result = RegisterLibraryFile(&fileSpec, &libFile);
  629.                         if (result)
  630.                             DebugBreak("RegisterLibraryFile failed");
  631.                         else
  632.                         {
  633.                             char    namebuffer[256];
  634.                             Trace("Library file registered: %s\n",libFile->GetVerboseName(namebuffer));
  635.                         }
  636.                     }
  637.                     break;
  638.                 }
  639.                 case iUnregisterFile:
  640.                 {
  641.                     SFTypeList    typelist;
  642.                     Point where = {100,150};
  643.                     SFReply reply;
  644.                     SFGetFile(where,(ConstStr255Param)"\pSelect a library file",NULL,-1,typelist,NULL,&reply);
  645.                     if (reply.good)
  646.                     {
  647.                         TMacFileSpec fileSpec(0,0,reply.fName);
  648.                         long    procID;
  649.                         GetWDInfo(reply.vRefNum,&fileSpec.fVRefNum,&fileSpec.fParID, &procID);
  650.                         OSErr result = UnregisterLibraryFileByFileSpec(&fileSpec, false);
  651.                         if (result)
  652.                             DebugBreak("UnregisterLibraryFileByFileSpec failed");
  653.                     }
  654.                     break;
  655.                 }
  656.                 case iReloadLibraryManager:
  657.                     fLibraryManagerCmd = kReloadLibraryManagerCmd;
  658.                     ExitLoop();
  659.                     break;
  660.                 case iUnloadLibraryManager:
  661.                     fLibraryManagerCmd = kUnloadLibraryManagerCmd;
  662.                     ExitLoop();
  663.                     break;
  664.                 case iGotoSimpleProgram:
  665.                     fLibraryManagerCmd = kGotoSimpleProgramCmd;
  666.                     ExitLoop();
  667.                     break;
  668.                 case iTraceLogOn:
  669.                     GetLocalLibraryManager()->TraceLogOn();
  670.                     break;
  671.                 case iTraceLogOff:
  672.                     GetLocalLibraryManager()->TraceLogOff();
  673.                     break;
  674.             }
  675.             break;
  676.         
  677.         case mTests: {
  678.                 switch (menuItem) {
  679.                     case iVerbose:
  680.                         {
  681.                             fVerbose = !fVerbose;
  682.                         }
  683.                         break;
  684.                         
  685.                     case iDebug:
  686.                         {
  687.                             fDebug = !fDebug;
  688.                         }
  689.                         break;
  690.  
  691.                     case iDoLoad:
  692.                         {
  693.                             fDoLoad = !fDoLoad;
  694.                         }
  695.                         break;
  696.                         
  697.                     case iGrowPool:
  698.                         {
  699.                             fGrowPool = !fGrowPool;
  700.                         }
  701.                         break;
  702.                         
  703.                     case iRunAllTests:
  704.                         {
  705.                             size_t idx = 0; 
  706.                             RgnHandle myRgn = NewRgn();    // a region to use for WaitNextEvent
  707.                             while (idx < fNumTests)
  708.                             {
  709.                                 RunTest(fTestsMenuTestList[idx++]);
  710.                                 EventRecord myEvent;
  711.                                 WaitNextEvent(nullEvent, &myEvent, 0, myRgn);
  712.                             }
  713.                             DisposeRgn(myRgn);
  714.                         }
  715.                         break;
  716.                         
  717.                     default:
  718.                         {
  719.                             TClassID* theTest = fTestsMenuTestList[menuItem-kTestsListStart];
  720.                             RunTest(theTest);
  721.                         }
  722.                         break;
  723.                 }
  724.                 
  725.             }
  726.             break;
  727.     }
  728.     
  729.     HiliteMenu(0);                    // unhighlight what MenuSelect (or MenuKey) hilited 
  730. }
  731.  
  732. /**********************************************************************
  733. ** PUBLIC DoNew
  734. ***********************************************************************/
  735.  
  736. // Create a new document and window. 
  737.  
  738. void  TInspector::DoNew(TRegisteredObjects *theObjects)
  739. {
  740.     if (fDocList->NumDocs() == kMaxDocuments)
  741.         return;
  742.     
  743.     TRegisteredObjectsWindow* tDoc;
  744.  
  745.     tDoc = new TRegisteredObjectsWindow(rDocWindow, theObjects, this);
  746.     // if we didn't get an allocation error, add it to list
  747.     if (tDoc != NULL) {
  748.         fDocList->AddDoc(tDoc);
  749.  
  750.         //
  751.         // Relocate the window. If this there is no saved info and this windows
  752.         // location then RestoreWindowLocation will return false.
  753.         //
  754.         if (!tDoc->RestoreWindowLocation())
  755.         {
  756.             tDoc->MoveWindow(fNextWindowLocation.h,fNextWindowLocation.v);
  757.             tDoc->SizeWindow(kWindowHSizeStart, kWindowVSizeStart);
  758.             fNextWindowLocation.h +=kWindowHStagger;
  759.             fNextWindowLocation.v +=kWindowVStagger;
  760.             if ((fNextWindowLocation.v > fqd->screenBits.bounds.bottom-60) ||
  761.                 (fNextWindowLocation.h > fqd->screenBits.bounds.right-60))
  762.             {
  763.                 fNextWindowLocation.v = kWindowVStart;
  764.                 fNextWindowLocation.h = fHTopWindowLocation;
  765.                 fHTopWindowLocation += kWindowHResetStagger;
  766.             }
  767.         }
  768.         ShowWindow(tDoc->GetDocWindow());
  769.     }
  770. }
  771.  
  772. /**********************************************************************
  773. ** PUBLIC Terminate
  774. ***********************************************************************/
  775.  
  776. // Clean up the application and exits. You might want to close all
  777. // of your documents (and ask the user to save them) here.
  778.  
  779. void TInspector::Terminate()
  780. {
  781.     ExitLoop();
  782. }
  783.  
  784. /**********************************************************************
  785. ** PUBLIC OpenPrefsFile
  786. ***********************************************************************/
  787.  
  788. #if GENERATINGPOWERPC
  789.     #define kInspectorPrefs "\pInspectorPPC Prefs"
  790. #else
  791.     #define kInspectorPrefs "\pInspector Prefs"
  792. #endif
  793.  
  794. void TInspector::OpenPrefsFile()
  795. {
  796.     long    dirID;
  797.     short    vRefNum;
  798.     OSErr err = FindFolder(-1, kPreferencesFolderType, true, &vRefNum, &dirID);
  799.     if (err)
  800.         fPrefsFileRefNum = -1;
  801.     else
  802.     {
  803.         HCreateResFile(vRefNum, dirID, (ConstStr255Param) kInspectorPrefs); 
  804.         fPrefsFileRefNum = HOpenResFile(vRefNum, dirID, 
  805.             (ConstStr255Param) kInspectorPrefs, fsRdWrPerm);
  806.     }
  807. }
  808.  
  809. /**********************************************************************
  810. ** PUBLIC ClosePrefsFile
  811. ***********************************************************************/
  812.  
  813. void TInspector::ClosePrefsFile()
  814. {
  815.     if (fPrefsFileRefNum != -1)
  816.         CloseResFile(fPrefsFileRefNum);
  817. }
  818.  
  819. /**********************************************************************
  820. ** PUBLIC GetPrefsFileRefNum
  821. ***********************************************************************/
  822.  
  823. short TInspector::GetPrefsFileRefNum()
  824. {
  825.     return fPrefsFileRefNum;
  826. }
  827.  
  828. /**********************************************************************
  829. ** PUBLIC RunTest
  830. ***********************************************************************/
  831.  
  832. static void Idle(RgnHandle myRgn)
  833. {
  834.     EventRecord myEvent;
  835.     WaitNextEvent(nullEvent, &myEvent, 0, myRgn);
  836. }
  837.  
  838. static int _CDECL myPrintFunc(const char* format, char* args)
  839. {
  840.     char outstring[256];
  841.     int ret = SLMvsprintf(outstring, format, args);
  842.     Trace(outstring);
  843.     return ret;
  844. }
  845.  
  846. void TInspector::RunTest(TClassID* testname)
  847. {
  848.     RgnHandle        myRgn = NewRgn();        // a region to use for WaitNextEvent
  849.     TTestTool*        tool = NULL;
  850.     OSErr             theErr;
  851.     TStandardPool*    thePool;
  852.     TPoolNotifier*    savedNotifier;
  853.     
  854.     Idle(myRgn);
  855.     
  856.     if (fVerbose)
  857.         Trace("INFO: Creating Tool %s\n", testname);
  858.  
  859.     if (fDoLoad)
  860.     {
  861.         if (fDebug)
  862.             DebugStr((ConstStr255Param)"\pAbout to load class");
  863.         theErr = LoadClass(*testname, true);
  864.         if (theErr != kNoError)
  865.         {
  866.             Trace("###LoadClass failed, error = %d\n", theErr);
  867.             return;
  868.         }
  869.     }
  870.     else if (fDebug)
  871.         DebugStr((ConstStr255Param)"\pAbout to new tool");
  872.  
  873.     thePool = GetLocalPool();
  874.     savedNotifier = thePool->GetNotifier();
  875.     if (!fGrowPool)
  876.         thePool->SetNotifier(NULL);
  877.  
  878.     tool = (TTestTool*)NewObjectWithParent(*testname, ClassID(kTTestToolID), &theErr);
  879.     if (theErr != kNoError)
  880.         Trace("###NewObject Error %d\n", theErr);
  881.     
  882.     if (tool == NULL)
  883.         Trace("### ERROR: Could not create Tool %s\n", testname);
  884.     else
  885.     {
  886.         tool->SetPool(thePool);
  887.         tool->SetPrintf(myPrintFunc);
  888.         
  889.         long count = fIterationCount;
  890.  
  891.         if (fVerbose)
  892.         {
  893.             Trace("****************** Begin Test *****************\n");
  894.             PoolInfo    info;
  895.             thePool->GetPoolInfo(info);
  896.             Trace("INFO: Pool size     = %d\n", info.fFreeBytes);
  897.             Trace("INFO: Largest Block = %d\n", info.fLargestBlock);
  898.         }
  899.         
  900.         tool->InitTest(fVerbose, fDebug, 0, NULL);
  901.         Idle(myRgn);
  902.         while (count--)
  903.         {
  904.             tool->RunTestIteration(fVerbose, fDebug);
  905.             Idle(myRgn);
  906.         }
  907.         tool->EndTest(fVerbose, fDebug);
  908.         Idle(myRgn);
  909.         
  910.         if (fVerbose)
  911.             Trace("INFO: Destroying Tool %s\n", testname);
  912.         if (fDebug)
  913.             DebugStr((ConstStr255Param)"\pAbout to destroy tool");
  914.         delete tool;
  915.  
  916.         if (fVerbose)
  917.         {
  918.             PoolInfo    info;
  919.             thePool->GetPoolInfo(info);
  920.             Trace("INFO: Pool size     = %d\n", info.fFreeBytes);
  921.             Trace("INFO: Largest Block = %d\n", info.fLargestBlock);
  922.             if (!fGrowPool)
  923.             {
  924.                 void* test = thePool->Allocate(kInspectorPoolSize*2);
  925.                 if (test != NULL)
  926.                 {
  927.                     Trace("ERROR: Allocated block larger than pool size!\n");
  928.                     thePool->GetPoolInfo(info);
  929.                     Trace("ERROR: Pool size     = \n", info.fFreeBytes);
  930.                     Trace("ERROR: Largest Block = \n", info.fLargestBlock);
  931.                     thePool->Free(test);
  932.                     thePool->GetPoolInfo(info);
  933.                     Trace("ERROR: Pool size     = \n", info.fFreeBytes);
  934.                     Trace("ERROR: Largest Block = \n", info.fLargestBlock);
  935.                 }
  936.                 else
  937.                 {
  938.                     thePool->GetPoolInfo(info);
  939.                     Trace("INFO: After freeing chunks -->");
  940.                     Trace("INFO: Pool size     = \n", info.fFreeBytes);
  941.                     Trace("INFO: Largest Block = \n", info.fLargestBlock);
  942.                 }
  943.             }
  944.         }
  945.         Idle(myRgn);
  946.     }
  947.  
  948.     if (fVerbose)
  949.         Trace("****************** End Test *****************\n");
  950.     
  951.     if (fDoLoad)
  952.         UnloadClass(*testname);
  953.  
  954.     DisposeRgn(myRgn);
  955. }
  956.